﻿using SQLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using TabbedTemplate.Models;

namespace TabbedTemplate.Services
{
    public class QueryService : IQueryService
    {
        // ******** 构造方法
        public QueryService(IPreferenceStorage preferenceStorage)
        {
            _preferenceStorage = preferenceStorage;
        }

        // ******** 公开常量
        /// <summary>
        /// 搜索内容数据库名。
        /// </summary>
        public const string DbName = "queryItemdb.sqlite3";

        // ******** 私有变量
        /// <summary>
        /// 搜索内容数据库路径。
        /// </summary>
        /// <returns></returns>
        public static readonly string QueryDbPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData), DbName);

        /// <summary>
        /// 数据库连接影子变量。
        /// </summary>
        private SQLiteAsyncConnection _connection;

        /// <summary>
        /// 数据库连接。
        /// </summary>
        public SQLiteAsyncConnection Connection
        {
            get => _connection ??= new SQLiteAsyncConnection(QueryDbPath);
            set => _connection = value;
        }


        private IPreferenceStorage _preferenceStorage;

        public bool Initialized() =>
            _preferenceStorage.Get(QueryServiceConstants.VersionKey, -1) ==
            QueryServiceConstants.Version;

        public async Task InitializeAsync()
        {
            await Connection.CreateTableAsync<SearchItemCache>();
            _preferenceStorage.Set(QueryServiceConstants.VersionKey,
                QueryServiceConstants.Version);
        }

        /// <summary>
        /// 判断当前的搜索是否有缓存。
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public async Task<SearchItemToReturn> GetSearchItemByString(
            string content, string cityName)
        {
            var res = await Connection.Table<SearchItemCache>()
                .FirstOrDefaultAsync(p =>
                    p.SearchContent == content && p.City == cityName);
            if (res == null)
            {
                return new SearchItemToReturn
                {
                    HasCache = false,
                    SearchItem = null
                };
            }

            return new SearchItemToReturn { HasCache = true, SearchItem = res };
        }

        public async Task InsertSearchItem(string content, string cityName)
        {
            var exist = await GetSearchItemByString(content, cityName);
            if (exist.HasCache)
            {
                exist.SearchItem.TimeStamp = DateTime.Now.Ticks;
                await ConnectionUpdateAsync(exist.SearchItem);
            }
            else
            {
                await ConnectionInsertAsync(new SearchItemCache
                {
                    SearchContent = content,
                    City = cityName,
                    TimeStamp = DateTime.Now.Ticks
                });
            }
        }

        public async Task<IList<SearchItemCache>> GetTenItems()
        {
            var res = await Connection.Table<SearchItemCache>().CountAsync();
            if (res <= 10)
            {
                var local = await Connection.Table<SearchItemCache>()
                    .OrderByDescending<long>(p => p.TimeStamp).ToListAsync();
                return local;
            }

            return await Connection.Table<SearchItemCache>()
                .OrderByDescending<long>(p => p.TimeStamp).Take(10)
                .ToListAsync();
        }

        public async Task CloseAsync() => await Connection.CloseAsync();
        public async Task ConnectionUpdateAsync(SearchItemCache searchItemCache)
        {
            await Connection.UpdateAsync(searchItemCache);
        }

        public async Task ConnectionInsertAsync(SearchItemCache searchItemCache)
        {
            await Connection.InsertAsync(searchItemCache);
        }

        public async Task DeleteSearchItemById(int id)
        {
            await Connection.DeleteAsync(id);
        }
    }

    public static class QueryServiceConstants
    {
        /// <summary>
        /// 版本。
        /// </summary>
        public const string VersionKey =
            nameof(IQueryService) + "." + nameof(Version);

        /// <summary>
        /// 版本。
        /// </summary>
        public const int Version = 1;
    }
}
